#include "RingQueue.hxx"
#include "thread.hpp"
using namespace std;


template <class T>
struct threadData{
    threadData(RingQueue<T>* data,const string &name)
    :_bq(data)
    ,_ThreadName(name)
    {

    }
    threadData(RingQueue<T>* data,string &&name)
    :_bq(data)
    ,_ThreadName(name)
    {

    }
    RingQueue<T> *_bq;
    string _ThreadName;
};

void *comsumer(void *args)
{
    RingQueue<string> *l_rq = static_cast<threadData<string>*>(args) ->_bq;
    for (int i = 0; i < 100;i++)
    {
        sleep(1); 
        string s;
        l_rq->Pop(&s);
        cout << static_cast<threadData<string> *>(args)->_ThreadName + "-> :Get:" + s +"\n";
    }
    return nullptr;
}

void* producer(void* args)
{
    RingQueue<string> *l_rq = static_cast<threadData<string> *>(args)->_bq;
    for (int i = 0; i < 100;i++)
    {
        // sleep(1);
        l_rq->Push(static_cast<threadData<string>*>(args)->_ThreadName + "-> :Add "  + to_string(i));
        cout << static_cast<threadData<string> *>(args)->_ThreadName + "-> :Add " + to_string(i) << endl;
        
    }
    return nullptr;
}


int main()
{
    RingQueue<string> *rq = new RingQueue<string>();
    
    vector<fuh::thread<void *>> thread_array;
    for (int i = 0; i < 2;i++)
    {
        threadData<string>* tdata = new threadData<string>(rq, "");
        tdata->_ThreadName = "Producer-" + to_string(i);
        thread_array.push_back(fuh::thread<void *>(producer, tdata));
    }
    for (int i = 0; i < 3;i++)
    {
        threadData<string>* tdata = new threadData<string>(rq, "");
        tdata->_ThreadName = "Consumer-" + to_string(i);
        thread_array.push_back(fuh::thread<void *>(comsumer, tdata));
    }

    for (int i = 0; i < thread_array.size();i++)
    {
        thread_array[i].Start();
    }
    for(auto &td:thread_array)
    {
        td.join();
    }
    return 0;
}